/*
This file is part of SharpPcap.

SharpPcap is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

SharpPcap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with SharpPcap.  If not, see <http://www.gnu.org/licenses/>.
*/
/* 
 * Copyright 2005 Tamir Gal <tamir@tamirgal.com>
 * Copyright 2008-2009 Chris Morgan <chmorgan@gmail.com>
 * Copyright 2008-2009 Phillip Lemon <lucidcomms@gmail.com>
 */

using SharpPcap.LibPcap;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

namespace SharpPcap
{
    /// <summary>
    /// Constants and static helper methods
    /// </summary>
    public class Pcap
    {
        /// <summary>Represents the infinite number for packet captures </summary>
  

        /* interface is loopback */
   
        internal const int      MAX_PACKET_SIZE                 = 65536;
        internal const int      PCAP_ERRBUF_SIZE                = 256;

        // Constants for address families
        // These are set in a Pcap static initializer because the values
        // differ between Windows and Linux
        internal readonly static int      AF_INET=2; // happens to have the same value on Windows and Linux
        internal readonly static int AF_PACKET = 17;  // AF_PACKET = 17 on Linux, AF_NETBIOS = 17 on Windows
                                                      // FIXME: need to resolve the discrepency at some point
        internal readonly static int AF_INET6 = 23; //value for windows from winsock.h

        public static List<LibPcapLiveDevice> Devices(string ip) {
            var retval = new List<LibPcapLiveDevice>();

            var devicePtr = IntPtr.Zero;
            var errorBuffer = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE); //will hold errors

            // convert the remote authentication structure to unmanaged memory if
            // one was specified
            IntPtr rmAuthPointer = IntPtr.Zero;


            int result = LibPcapSafeNativeMethods.pcap_findalldevs_ex("rpcap://", rmAuthPointer, ref devicePtr, errorBuffer);
            // free the memory if any was allocated
            if (rmAuthPointer != IntPtr.Zero)
                Marshal.FreeHGlobal(rmAuthPointer);

            if (result < 0)
                throw new Exception(errorBuffer.ToString());

            IntPtr nextDevPtr = devicePtr;

            while (nextDevPtr != IntPtr.Zero) {
                // Marshal pointer into a struct
                var pcap_if_unmanaged = (PcapUnmanagedStructures.pcap_if)Marshal.PtrToStructure(nextDevPtr,  typeof(PcapUnmanagedStructures.pcap_if));
                PcapInterface pcap_if = new PcapInterface(pcap_if_unmanaged);

                // create an airpcap device if the device appears to be a
                // airpcap device
                var winpcapDevice = new LibPcapLiveDevice(pcap_if);
                if (!winpcapDevice.Name.Contains("airpcap")) {
                    retval.Add(new LibPcapLiveDevice(pcap_if));
                }
                nextDevPtr = pcap_if_unmanaged.Next;
            }

            LibPcap.LibPcapSafeNativeMethods.pcap_freealldevs(devicePtr);  // Free unmanaged memory allocation.

            return retval;
        }
    }
}
